Amazon VPCを使ったサーバ環境をコマンドラインツールで構築する
はじめに
こんにちは植木和樹です。5月8日よりクラスメソッドでの業務を開始しました。これからよろしくお願いします。
さてAWSが提供する各種サービスについていろいろ試していくにあたり、まずは実験できるサーバ環境を作っておくと便利です。というわけで今回はVPCでサーバ環境を構築してみたいと思います。
VPCを使ったサーバ構築手順については、すでに弊社ブログ「Amazon VPCを使ったミニマム構成のサーバ環境を構築する」でAWS Management Consoleによる手順を取り上げています。これではネタがかぶってしまいますので、今回コマンド操作が大好きな私はAmazon EC2 Command Line Tools(以下CLIツール)を使ってコマンドラインで環境構築してみたいと思います。実験環境なので作っては破棄しまた作り直し・・・を何度もすることになると思うので再利用性の高いやり方にしておきたいところです。
今回の構成
VPC内にパブリックとプライベート、2つのサブネットを作成します。
今回は特にミニマム構成を想定していませんので、プライベートサブネットにEC2を1つRDSを1つ、パブリックサブネットにはEC2を1つとプライベートEC2のNAT用インスタンスを1つ、計4インスタンスを作成します。
上の図で青い線がインターネットからPublic Server上のアプリケーションを介してMySQLに接続するまでの通信の流れを表しています。また緑色の線はPrivate ServerがNATインスタンスを通じてインターネットと接続する際の通信の流れを表しています。
環境構築にあたっては以下のブログを参考にしました。先に目を通していただければ、より理解が深まると思いますので是非ご参照ください。("PrivateServer"へは"Public Server"を踏み台にしてssh接続します)
- Amazon VPCを使ったミニマム構成のサーバ環境を構築する
- Amazon VPCでELBとNATを使ってよりセキュアな環境を作る【5日目】
- Amazon VPC環境にメンテナンス用の踏み台サーバを構築する
いきなりの結論
具体的な構築手順は後ほどご説明するとして、今回はいきなり結論です。
CLIツールで環境構築はしないことがオススメ
CLIツールでの構築は正直とても面倒でした。構築するだけならManagement Consoleの使用を「強く、強く」オススメします。特にAWSが初めての方はAWS Management Consoleを使ってください。Management ConsoleのGUIはとても良くできていますので、CLIツールよりも早く簡単に構築できるはずです。
なにが面倒だったといいますとVPCやEC2インスタンス作成ごとに生成される各種IDの把握が手間でした。例えばVPCとサブネット、サブネットとEC2インスタンスなど各種リソースを関連づけるときにはコマンドラインオプションでリソースのIDを指定する必要があります。が、このIDは環境を構築する際に決まるため、CLIツールを使った場合にはリソースを作成するたびにIDを調べメモに控えておく作業が必要になります。さらに今回は複数のサブネットやEC2インスタンスを作成したので、どのIDがどのリソースに対応しているかを別途Excelで管理・参照しながら進めていました。
Management ConsoleだとタグやIPアドレスなどメタ情報が表示された項目をプルダウンメニューで選択できるので、この手間を省くことができます。
目的別のツール使い分け
目的別に次のようにツールを使い分けるのが良いかと思います。
- とにかく環境を構築したい
- ・・・AWS Management Consoleを使う
- 再利用できる環境構築手段を用意したい
- ・・・CloudFormationのテンプレートを作成する
- 障害発生時などシェルから部分的に構成を変更したい
- ・・・シェルからCLIツールを実行する
学習教材としてCLIツールでの環境構築はオススメ
Management Consoleだと初期値になっていたり自動的に関連づけがされている画面でも、CLIツールでは明示的に指定しなければいけません。そのため、その設定にどんな意味があるのか、なにをパラメータで指定してあげなければならないのかを考えるいい機会になったと思います。
設定が足りなかったり、間違っていたりした場合には当然通信できませんので、うまくいかない原因を考える良い訓練にもなります。コマンドでの作業のため、実行したコマンドや実行結果などの作業記録はターミナルのログとして保存しておけますから、後から識者にレビューしてもらいやすい点もメリットです。AWS学習教材の一つとしてコマンドラインでの構築訓練はアリだと感じました。
CLIツールでの環境構築
さて、ここまでで本ブログでやりたかったことと結論はすでに述べました。以降はVPC上でのサーバ環境構築をCLIツールでやる場合はこういう風にするんだよ、という作業記録をご紹介していきます。なにかの機会にみなさまの参考になれば幸いです。
CLIツールの環境準備
CLIツールを使うには環境設定が必要です。今回は作業用EC2インスタンスを別途用意して作業を行いました。Amazon Linuxならツール(Java版)が最初からインストール済みですので、環境変数 AWS_ACCESS_KEY と AWS_SECRET_KEY を設定するだけで始められます。
(IAMユーザの場合は適切な権限を与えておいてください)
以降、特に断りがなければ作業はこの作業用EC2インスタンスで行っています。
作業の流れ
作業自体は結構なボリュームがあるので、最初に全体の流れを把握しておきましょう。
- VPCとサブネットの作成
- VPCを作成する
- サブネットを作成する
- Network ACLを設定する
- プライベートサブネット用のルートテーブルを作成する
- パブリックサブネット用のルートテーブルを作成する
- インターネット・ゲートウェイを作成する
- パブリックサブネット用ルートテーブルにインターネット・ゲートウェイを設定する
- Public Serverの構築
- セキュリティグループを作成する
- EC2インスタンスを起動する
- インスタンスにタグで名前をつける
- Elastic IPアドレスを割り当てる
- sshで接続できることを確認する
- Private Serverの構築
- セキュリティグループを作成する
- EC2インスタンスを起動する
- インスタンスにタグで名前をつける
- Public Server経由でsshで接続できることを確認する
- NAT Serverの構築
- セキュリティグループを作成する
- EC2インスタンスを起動する
- インスタンスにタグで名前をつける
- Elastic IPアドレスを割り当てる
- プライベートサブネット用ルートテーブルにNATインスタンスを設定する
- Public Server経由でsshで接続できることを確認する
- Private Serverでyumが使えることを確認する
- RDSインスタンスの起動
- セキュリティグループを作成する
- DB用パラメータグループを作成する
- DB用サブネットグループを作成する
- RDSインスタンスを起動する
- Public Serverからmysqlで接続できることを確認する
VPCとサブネットの作成
VPCを作成する
CIDR形式で使用するネットワークアドレスを指定します。コマンド実行結果としてVPC IDが表示されます。後々のコマンドでVPCを指定する際に使用しますのでvpc-で始まるIDをメモしておきましょう。
$ ec2-create-vpc 10.0.0.0/16 VPC vpc-fdf9e794 pending 10.0.0.0/16 dopt-f1f9e798 default
サブネットを作成する
サブネットを3つ作成します。コマンド実行結果としてSUBNET IDが表示されます。後々のコマンドでサブネットを指定する際に使用しますのでsubnet-で始まるIDをメモしておきましょう。
「今回の構成」でも書きましたが3つ目のサブネットはRDS用に使いますので、プライベートサブネットとは異なるAZを指定してあげる必要があります。
$ ec2-create-subnet --vpc vpc-fdf9e794 --cidr 10.0.0.0/24 SUBNET subnet-2af6e843 pending vpc-fdf9e794 10.0.0.0/24 251 ap-northeast-1a $ ec2-create-subnet --vpc vpc-fdf9e794 --cidr 10.0.1.0/24 SUBNET subnet-22f6e84b pending vpc-fdf9e794 10.0.1.0/24 251 ap-northeast-1a $ ec2-create-subnet --vpc vpc-fdf9e794 --cidr 10.0.2.0/24 --availability-zone ap-northeast-1c SUBNET subnet-c08f91a9 pending vpc-fdf9e794 10.0.2.0/24 251 ap-northeast-1c
Network ACLを設定する
Network ACLはVPC作成時に自動的に作成されます。このデフォルトのACLは全てのInbound/Outboundの通信を許可します。今回通信の可否はセキュリティグループで設定しますので、このままデフォルトのACLを使用することにします。
プライベートサブネット用のルートテーブルを作成する
ルート・テーブルもACLと同様、自動的に1つ作成されます。これはメイン・ルート・テーブルになっていて、サブネットに対して明示的にルート・テーブルを指定しなかった場合にデフォルトで使用されます。
今回はこのメイン・ルート・テーブルをプライベートネットワーク用として使用することにします。なおルート・テーブルIDが後々必要になりますので以下のコマンドで確認し、rtb-で始まるIDをメモしておいてください。
$ ec2-describe-route-tables
パブリックサブネット用のルートテーブルを作成する
パブリックサブネット用のルートテーブルを作成し、パブリック・サブネットに紐付けます。対象のVPCやサブネットには先ほどメモしておいたIDを指定してください。
$ ec2-create-route-table vpc-fdf9e794 ROUTETABLE rtb-bd9a84d4 vpc-fdf9e794 ROUTE local active 10.0.0.0/16 CreateRouteTable $ ec2-associate-route-table rtb-bd9a84d4 --subnet subnet-2af6e843 ASSOCIATION rtbassoc-c19b85a8 rtb-bd9a84d4 subnet-2af6e843
インターネット・ゲートウェイを作成する
インターネット・ゲートウェイを作成し、VPCに紐付けます。igw-で始まるIDをメモしておきましょう。
$ ec2-create-internet-gateway INTERNETGATEWAY igw-27f0ee4e $ ec2-attach-internet-gateway igw-27f0ee4e --vpc vpc-fdf9e794 ATTACHMENT vpc-fdf9e794 attaching
パブリックサブネット用ルートテーブルにインターネット・ゲートウェイを設定する
作成したインターネット・ゲートウェイをパブリック・サブネットのデフォルト・ゲートウェイ(0.0.0.0/0)に設定します。
$ ec2-create-route rtb-bd9a84d4 --gateway igw-27f0ee4e --cidr 0.0.0.0/0 ROUTE igw-27f0ee4e 0.0.0.0/0
ここまででVPCと各サブネットの作成は完了です、次に各サブネットにEC2インスタンスを作成していきます。
Public Serverの構築
セキュリティグループを作成する
インターネットからSSH(tcp/22), HTTP(tcp/80)の接続を許可します。セキュリティグループ作成時に表示されるID(sg-7bced717)は、後ほど他のセキュリティグループを設定する際にも使用しますのでメモしておいてください。
$ ec2-create-group my-sg-test-pub --vpc vpc-fdf9e794 -d "SG for public server" GROUP sg-7bced717 my-sg-test-pub SG for public server $ ec2-authorize sg-7bced717 -P tcp -p 22 GROUP sg-7bced717 PERMISSION ALLOWS tcp 22 22 FROM CIDR 0.0.0.0/0 ingress $ ec2-authorize sg-7bced717 -P tcp -p 80 GROUP sg-7bced717 PERMISSION ALLOWS tcp 80 80 FROM CIDR 0.0.0.0/0 ingress
EC2インスタンスを起動する
Public ServerのOSにはAmazon Linuxを使用しました。インスタンスタイプはt1.microです。
EC2インスタンスをVPC内に作成するので --subnet でVPCサブネットを指定します。VPCを利用する場合セキュリティグループ(--group)には名前でなくID(sg-XXXX)で指定する必要がありますので注意してください。
コマンドの実行結果は載せていませんが、インスタンスの作成が成功するとインスタンスIDが表示されます。i-で始まるIDをメモしておいてください。
$ ec2-run-instances \ --subnet subnet-2af6e843 \ --group sg-7bced717 \ --instance-type t1.micro \ --instance-count 1 \ --key <MY_KEYNAME> \ ami-173fbf16
インスタンスにタグで名前をつける
あとでAWS Management Consoleなどを見たときに区別しやすいよう、EC2インスタンスには名前をつけておきましょう。
$ ec2-create-tags i-3f1fcb3d --tag Name=public TAG instance i-3f1fcb3d Name public
Elastic IPアドレスを割り当てる
Elastic IPはVPCで使用する場合 --domain vpc の指定が必要です。またIP発行結果として eipalloc-XXXXXXXX というIDが表示されます。このIDをEC2インスタンスに割り当てる際に --allocation-id で指定します。
$ ec2-allocate-address --domain vpc ADDRESS 54.249.XXX.XXX vpc eipalloc-fff3ed96 $ ec2-associate-address --instance i-3f1fcb3d --allocation-id eipalloc-fff3ed96 ADDRESS i-3f1fcb3d eipalloc-fff3ed96 eipassoc-d6f0eebf
sshで接続できることを確認する
ここまででPublic Serverの構築は完了です。Elastic IPを指定してsshでログインできることを確認しましょう。
Private Serverの構築
セキュリティグループを作成する
Public ServerからのみSSH(tcp/22), SNMP(udp/161)の接続を許可します。接続元をPublic Serverからのみに限定するには、Public Server作成時に指定したセキュリティグループID(sg-7bced717)を利用します。
$ ec2-create-group my-sg-test-pri --vpc vpc-fdf9e794 -d "SG for private server" GROUP sg-75ced719 my-sg-test-pri SG for private server $ ec2-authorize sg-75ced719 -P tcp -p 22 --source-or-dest-group sg-7bced717 GROUP sg-75ced719 PERMISSION ALLOWS tcp 22 22 FROM USER ID sg-7bced717 ingress $ ec2-authorize sg-75ced719 -P udp -p 161 --source-or-dest-group sg-7bced717 GROUP sg-75ced719 PERMISSION ALLOWS udp 161 161 FROM USER ID sg-7bced717 ingress
EC2インスタンスを起動する
Public Serverと同じくAmazon Linuxを使用します。異なる点はサブネット(--subnet)とセキュリティグループ(--group)の2カ所です。
$ ec2-run-instances \ --subnet subnet-22f6e84b \ --group sg-75ced719 \ --instance-type t1.micro \ --instance-count 1 \ --key <MY_KEYNAME> \ ami-173fbf16
インスタンスにタグで名前をつける
あとでAWS Management Consoleなどを見たときに区別しやすいよう、EC2インスタンスには名前をつけておきましょう。
$ ec2-create-tags i-2118cc23 --tag Name=private TAG instance i-2118cc23 Name private
Public Server経由でsshで接続できることを確認する
ここまででPrivate Serverの構築は完了です。Public Serverを踏み台にしてsshでログインできることを確認しましょう。
【参考】Amazon VPC環境にメンテナンス用の踏み台サーバを構築する
NATサーバの構築
Private ServerはElastic IPを持たないため外部と通信できずyumなどが使用できません。NATサーバ経由で通信できるようにしましょう。
【参考】Amazon VPCでELBとNATを使ってよりセキュアな環境を作る【5日目】
セキュリティグループを作成する
NATサーバは次の2つの通信のみ許可します。
- Private ServerからのHTTP(tcp/80) ... yumのため
- Public ServerからのSSH(tcp/22)
それぞれ接続元を限定するためにSUBNET IDを指定します。
$ ec2-create-group my-sg-test-nat --vpc vpc-fdf9e794 -d "SG for NAT (public subnet)" GROUP sg-c9c0d9a5 my-sg-test-nat SG for NAT (public subnet) $ ec2-authorize sg-c9c0d9a5 -P tcp -p 80 --source-or-dest-group sg-75ced719 GROUP sg-c9c0d9a5 PERMISSION ALLOWS tcp 80 80 FROM USER ID sg-75ced719 ingress $ ec2-authorize sg-c9c0d9a5 -P tcp -p 22 --source-or-dest-group sg-7bced717 GROUP sg-c9c0d9a5 PERMISSION ALLOWS tcp 22 22 FROM USER ID sg-7bced717 ingress
EC2インスタンスを起動する
NATサーバ用のインスタンスにはAmazonで提供しているNAT用AMI(ami-12d86d13)を使用します。Public Server用EC2インスタンスの作成コマンドと異なる点はセキュリティグループ(--group)とAMIの2カ所です。
$ ec2-run-instances \ --subnet subnet-2af6e843 \ --group sg-c9c0d9a5 \ --instance-type t1.micro \ --instance-count 1 \ --key <MY_KEYNAME> \ ami-12d86d13
インスタンスにタグで名前をつける
あとでAWS Management Consoleなどを見たときに区別しやすいよう、EC2インスタンスには名前をつけておきましょう。
$ ec2-create-tags i-fdf92eff --tag Name=nat TAG instance i-fdf92eff Name nat
Elastic IPアドレスを割り当てる
Public Serverの時と同様の手順で、Elastic IPをNATサーバに割り当てます。
$ ec2-allocate-address --domain vpc ADDRESS 54.249.XXX.XXX vpc eipalloc-1339217a $ ec2-associate-address --instance i-fdf92eff --allocation-id eipalloc-1339217a ADDRESS i-fdf92eff eipalloc-1339217a eipassoc-f1392198
プライベートサブネット用ルートテーブルにNATインスタンスを設定する
Private Serverが外部と接続する際に、NATインスタンスを経由するようプライベートサブネット用ルートテーブルを設定します。--gateway でなく --instance で指定するところがポイントです。
$ ec2-create-route rtb-fff9e796 --instance i-fdf92eff --cidr 0.0.0.0/0 ROUTE i-fdf92eff 0.0.0.0/0
Public Server経由でsshで接続できることを確認する
これでNATサーバの準備ができました。Public Serverを踏み台にしてsshでログインできることを確認しましょう。
Private Serverでyumが使えることを確認する
NATサーバが起動していれば、Private ServerもVPCの外部に接続できるようになっているはずです。Private Serverにsshでログインしyumが使えるか確認しましょう。
RDSインスタンスの起動
プライベートサブネット内にRDS(MySQL)インスタンスを作成します。
セキュリティグループを作成する
Public ServerからのみMySQL(tcp/3306)の接続を許可します。
$ ec2-create-group my-sg-mysql --vpc vpc-fdf9e794 -d "SG for mysql (private subnet)" GROUP sg-1bc1d877 my-sg-mysql SG for mysql (private subnet) $ ec2-authorize sg-1bc1d877 -P tcp -p 3306 --source-or-dest-group sg-7bced717 GROUP sg-1bc1d877 PERMISSION ALLOWS tcp 3306 3306 FROM USER ID sg-7bced717 ingress
DB用パラメータグループを作成する
$ rds-create-db-parameter-group my-dbpg-test-mysql55 \ --db-parameter-group-family mysql5.5 \ -d "DB ParameterGroup for testdb(mysql-5.5)" DBPARAMETERGROUP my-dbpg-test-mysql55 mysql5.5 DB ParameterGroup for testdb(mysql-5.5)
DB用サブネットグループを作成する
RDSをMulti-AZ構成にする場合にレプリケーションが作成される複数のAZを「サブネットグループ」として定義します。--db-subnet-list にVPCサブネットのIDを最低2つ以上指定してください。
$ rds-create-db-subnet-group \ --db-subnet-group-name my-dsg-test \ --db-subnet-group-description "DB SubnetGroup for test" \ --db-subnet-list subnet-22f6e84b,subnet-c08f91a9 SUBNETGROUP my-dsg-test DB SubnetGroup for test Complete vpc-fdf9e794 SUBNET subnet-c08f91a9 ap-northeast-1c Active SUBNET subnet-22f6e84b ap-northeast-1a Active
RDSインスタンスを起動する
MySQLのサーバ名は testsv、MySQLデータベース名は testdb にします。今回はテストのためバックアップはひとまず無効にしています。
$ rds-create-db-instance testsv \ --db-subnet-group-name my-dsg-test \ --vpc-security-group-ids sg-1bc1d877 \ --db-instance-class db.t1.micro \ --engine mysql \ --db-parameter-group-name my-dbpg-test-mysql55 \ --db-name testdb \ --master-username testuser \ --master-user-password testuser \ --allocated-storage 5 \ --backup-retention-period 0 DBINSTANCE testsv db.t1.micro mysql 5 testuser creating 0 **** n 5.5.27 general-public-license n VPCSECGROUP sg-1bc1d877 active SUBNETGROUP my-dsg-test DB SubnetGroup for test Complete vpc-fdf9e794 SUBNET subnet-c08f91a9 ap-northeast-1c Active SUBNET subnet-22f6e84b ap-northeast-1a Active PARAMGRP my-dbpg-test-mysql55 in-sync OPTIONGROUP default:mysql-5-5 in-sync
Public Serverからmysqlで接続できることを確認する
Public Serverにsshでログインして、mysqlコマンドで接続できるか確認します。
$ sudo yum -y install mysql $ mysql -u testuser -ptestuser -h testsv.c9cxowny4ezp.ap-northeast-1.rds.amazonaws.com testdb